<template>
  <div>
    <div style="position: relative">
      <el-page-header @back="toBack" :content="selectGridData.fullPathText">
      </el-page-header>
      <div style="position: absolute; left: 40%; z-index: 99; top: -10px">
        <div style="display: flex; justify-content: center" v-if="planeImgUrl != ''">
          <el-button type="primary" @click="toSave" style="margin-right: 30px"
            >保存</el-button
          >

          <el-button type="primary" plain @click="toReset" style="margin-right: 30px"
            >全部点位重置</el-button
          >

          <el-button type="primary" @click="toResetCanvas">重置图纸</el-button>
        </div>
      </div>
      <div style="position: absolute; right: 10px; top: 0px; color: #409eff">
        温馨提示：拖拽平面图需按住alt键。
      </div>
    </div>

    <div
      class="content"
      :style="{
        height: contentHeight + 'px',
      }"
    >
      <div class="box-left">
        <el-card shadow="never" class="device-info" style="overflow: auto">
          <div
            v-for="(item, index) in deviceGroupList"
            :key="index"
            style="margin-bottom: 15px"
          >
            <div class="device-type">
              <i
                class="el-icon-caret-bottom"
                v-if="item.expandAll"
                @click="item.expandAll = !item.expandAll"
              ></i>
              <i
                class="el-icon-caret-right"
                v-if="!item.expandAll"
                @click="item.expandAll = !item.expandAll"
              ></i>
              {{ item.deviceTypeStr }}列表
            </div>
            <div v-if="item.expandAll">
              <div style="padding: 5px 10px">
                <el-input
                  size="mini"
                  placeholder="请输入设备名"
                  v-model="item.inputKey"
                  :clearable="true"
                  @input="onInputKeyChange(index)"
                ></el-input>
              </div>
              <div>
                <el-radio-group
                  v-model="selectedDeviceCode"
                  @change="onSelectedDeviceChange(index)"
                >
                  <template v-for="(item1, index1) in item.deviceList">
                    <el-radio
                      :key="index1"
                      :label="item1.deviceCode"
                      class="device-type-item"
                      v-if="
                        !item1.pointX ||
                        item1.pointX == '' ||
                        !item1.pointY ||
                        item1.pointY == ''
                      "
                      >{{ item1.deviceName }}</el-radio
                    >
                  </template>
                </el-radio-group>
              </div>
              <div v-if="item.deviceList.length == 0" style="margin-left: 20px">
                无设备数据。
              </div>
            </div>
          </div>
        </el-card>
      </div>
      <div class="box-right device-info" id="card">
        <canvas
          id="canvas"
          style="width: 100%; height: 100%"
          v-if="planeImgUrl != ''"
        ></canvas>

        <el-card
          shadow="never"
          v-if="planeImgUrl == ''"
          style="width: 100%; height: 100%"
        >
          <div style="text-align: center; margin-top: 20%; font-size: 20px">
            该网格没有上传2D平面图。
          </div>
        </el-card>

        <!-- 设备信息弹窗 -->
        <div
          class="info-popper"
          :style="{
            top: dialogPointY + 'px',
            left: dialogPointX + 'px',
          }"
          v-if="isShowInfoPopover"
        >
          <div>
            <div class="info-item">
              <span style="color: #525e8c">设备名称：</span>{{ infoObj.deviceName }}
            </div>
            <div class="info-item">
              <span style="color: #525e8c">设备编码：</span>{{ infoObj.deviceCode }}
            </div>
            <div class="info-item">
              <span style="color: #525e8c">设备类型：</span
              >{{ infoObj.type == "监控设备" ? "监控设备" : infoObj.deviceTypeStr }}
            </div>
            <div>
              <span style="color: #525e8c">设备状态：</span
              >{{ infoObj.deviceRunningState }}
            </div>
          </div>
          <div style="position: absolute; right: 0px; bottom: 10px">
            <el-button
              size="mini"
              type="danger"
              style="padding: 6px 15px"
              @click="toDelete"
              >删除</el-button
            >
            <el-button
              size="mini"
              style="padding: 6px 15px"
              @click="isShowInfoPopover = false"
              >关闭</el-button
            >
          </div>
          <div class="info-popper-arrow"></div>
        </div>
      </div>
    </div>
  </div>
</template>
<script>
import GridManageApi from "@/api/grid-manage";
import { fabric } from "fabric";
export default {
  name: "Binding",
  props: {
    selectGridData: {
      type: Object,
      default: () => {
        return {};
      },
    },
    deviceDictionaries: {
      type: Array,
      default: () => {
        return [];
      },
    },
  },

  computed: {
    isReplacePlan() {
      setTimeout(() => {
        if (this.$store.state.global.isReplacePlan) {
          this.$store.commit("global/setIsReplacePlan", false);
        }
      }, 2 * 1000);
      return this.$store.state.global.isReplacePlan;
    },
  },

  watch: {
    isReplacePlan: {
      handler(e) {
        if (e) {
          this.toBack();
        }
      },
    },
  },
  data() {
    return {
      contentHeight: 0,

      deviceList: [],
      deviceGroupList: [],
      selectedDeviceCode: "",
      selectedDeviceObj: {},

      cameraList: [],

      planeImgUrl: "",
      planeImgElement: null,
      deviceImgUrl: require("@/assets/acquisitionDevice.png"),
      cameraImgUrl: require("@/assets/cameraDevice1.png"),

      canvasWidth: 0,
      canvasHeight: 0,
      canvasObj: null,

      isShowInfoPopover: false,
      infoObj: {},
      deleteDevicePoint: null,

      firstDialogPointX: 0,
      firstDialogPointY: 0,
      dialogPointX: 0,
      dialogPointY: 0,
    };
  },
  created() {
    let clientHeight = 0;
    if (
      document.body.scrollHeight === window.screen.height &&
      document.body.scrollWidth === window.screen.width
    ) {
      clientHeight = window.screen.height - 5; // 网页可见区域高
    } else {
      clientHeight = document.body.clientHeight - 5; // 网页可见区域高
    }
    this.contentHeight = clientHeight - 180;
  },
  mounted() {
    this.getList2DPoint();
  },
  methods: {
    toBack() {
      this.$emit("back");
    },

    getList2DPoint() {
      const groupList = [
        {
          deviceTypeStr: "采集设备",
          deviceList: [],
          deviceList_copy: [],
          inputKey: "",
          expandAll: true,
        },
        {
          deviceTypeStr: "监控设备",
          deviceList: [],
          deviceList_copy: [],
          inputKey: "",
          expandAll: true,
        },
      ];
      const P1 = GridManageApi.getList2DPoint(this.selectGridData.guid);
      const P2 = GridManageApi.getListCamera2DPoint(this.selectGridData.guid);

      Promise.all([P1, P2]).then((res) => {
        this.deviceList = res[0].data;
        this.cameraList = res[1].data;

        this.deviceList.forEach((ele, idx) => {
          this.deviceDictionaries.forEach((ele1) => {
            if (ele.deviceType == ele1.dictValue) {
              ele.deviceTypeStr = ele1.dictText;
            }
          });
        });

        groupList.forEach((ele) => {
          this.deviceList.forEach((item) => {
            if (ele.deviceTypeStr == "采集设备") {
              ele.deviceList.push(item);
              ele.deviceList_copy.push(item);
            }
          });

          this.cameraList.forEach((item) => {
            if (ele.deviceTypeStr == "监控设备") {
              ele.deviceList.push(item);
              ele.deviceList_copy.push(item);
            }
          });
        });

        this.deviceGroupList = groupList;

        this.getPlaneImgUrl();
      });
    },
    onInputKeyChange(idx) {
      const item = this.deviceGroupList[idx];
      if (item.inputKey == "") {
        item.deviceList = item.deviceList_copy;
      } else {
        item.deviceList = item.deviceList_copy.filter(
          (p) => p.deviceName.indexOf(item.inputKey) > -1
        );
      }
    },
    onSelectedDeviceChange(idx) {
      this.deviceGroupList[idx].deviceList.forEach((ele) => {
        if (ele.deviceCode == this.selectedDeviceCode) {
          this.selectedDeviceObj = ele;
          this.selectedDeviceObj.type = this.deviceGroupList[idx].deviceTypeStr;
        }
      });
    },
    getPlaneImgUrl() {
      GridManageApi.getGridDetail(this.selectGridData.guid).then((ret) => {
        this.planeImgUrl = ret.data.files ? ret.data.files.url : "";
        if (this.planeImgUrl && this.planeImgUrl != "") {
          this.drawCanvas();
        }
      });
    },

    // 画图
    drawCanvas() {
      this.$nextTick(() => {
        this.planeImgElement = document.createElement("img");
        this.planeImgElement.src = this.planeImgUrl;
        this.planeImgElement.onload = () => {
          const cw = this.planeImgElement.width;
          const ch = this.planeImgElement.height;
          this.canvasWidth = cw;
          this.canvasHeight = ch;

          this.canvasObj = new fabric.Canvas("canvas", {
            // preserveObjectStacking: false, // 禁⽌选中图层时⾃定置于顶部
            fireRightClick: true, // 启用右键，button的数字为3
            stopContextMenu: true, // 禁止默认右键菜单
          });
          this.canvasObj.setWidth(this.canvasWidth); //设置画布宽度
          this.canvasObj.setHeight(this.canvasHeight); //设置画布⾼度

          this.canvasObj.setBackgroundImage(
            this.planeImgUrl,
            this.canvasObj.renderAll.bind(this.canvasObj),
            {
              scaleY: 1,
              scaleX: 1,
            }
          );
          // 滚轮缩放
          this.canvasObj.on("mouse:wheel", (opt) => {
            const delta = opt.e.deltaY; // 滚轮，向上滚一下是 -100，向下滚一下是 100
            let zoom = this.canvasObj.getZoom(); // 获取画布当前缩放值
            zoom *= 0.999 ** delta;
            if (zoom > 20) zoom = 20;
            if (zoom < 0.01) zoom = 0.01;

            // 以左上角为原点
            // this.canvas.setZoom(zoom)

            // 以鼠标所在位置为原点缩放
            this.canvasObj.zoomToPoint(
              {
                // 关键点
                x: opt.e.offsetX,
                y: opt.e.offsetY,
              },
              zoom
            );
            opt.e.preventDefault();
            opt.e.stopPropagation();

            this.isShowInfoPopover = false;
          });
          let isDragging = false;
          let lastPosX = 0;
          let lastPosY = 0;
          // alt+按下鼠标事件
          this.canvasObj.on("mouse:down", (opt) => {
            var evt = opt.e;
            if (evt.altKey === true) {
              isDragging = true;
              lastPosX = evt.clientX;
              lastPosY = evt.clientY;
            }
          });

          // 移动鼠标事件
          this.canvasObj.on("mouse:move", (opt) => {
            if (isDragging) {
              var e = opt.e;
              var vpt = this.canvasObj.viewportTransform;
              vpt[4] += e.clientX - lastPosX;
              vpt[5] += e.clientY - lastPosY;
              this.canvasObj.requestRenderAll();
              lastPosX = e.clientX;
              lastPosY = e.clientY;
            }
          });

          // 松开鼠标事件
          this.canvasObj.on("mouse:up", (opt) => {
            this.canvasObj.setViewportTransform(this.canvasObj.viewportTransform);
            if (isDragging) {
              const vpt = this.canvasObj.viewportTransform;
              this.dialogPointX = this.firstDialogPointX + vpt[4];
              this.dialogPointY = this.firstDialogPointY + vpt[5];

              this.isShowInfoPopover = false;
            }

            isDragging = false;
          });

          const a = document.getElementById("card");
          a.oncontextmenu = function () {
            // return false
            const _event = window.event || e; //事件对象
            if (_event.preventDefault) {
              _event.preventDefault(); //标准格式
            } else {
              _event.returnValue = false; //IE格式
            }
          };

          this.deviceGroupList.forEach((ele) => {
            ele.deviceList.forEach((item) => {
              if (item.pointX && item.pointX != "" && item.pointY && item.pointY != "") {
                this.toAddDevicePoint(
                  item.pointX,
                  item.pointY,
                  item.deviceCode,
                  ele.deviceTypeStr
                );
              }
            });
          });

          this.canvasObj.on("mouse:down", (event) => {
            if (event.button == 1) {
              if (this.selectedDeviceObj.deviceCode) {
                // this.selectedDeviceObj.pointX = event.e.layerX;
                // this.selectedDeviceObj.pointY = event.e.layerY;
                this.selectedDeviceObj.pointX = event.absolutePointer.x;
                this.selectedDeviceObj.pointY = event.absolutePointer.y;
                this.toAddDevicePoint(
                  this.selectedDeviceObj.pointX,
                  this.selectedDeviceObj.pointY,
                  this.selectedDeviceObj.deviceCode,
                  this.selectedDeviceObj.type
                );
              }
            }
          });
        };
      });
    },

    // 绑定设备点位
    toAddDevicePoint(x, y, id, type) {
      const img = new Image();
      const imgWidth = 32;
      img.src = type == "采集设备" ? this.deviceImgUrl : this.cameraImgUrl;
      img.style.width = imgWidth + "px";
      img.style.height = imgWidth + "px";
      img.onload = () => {
        const devicePointImg = new fabric.Image(img, {
          left: x - imgWidth / 2,
          top: y - imgWidth / 2,
          width: imgWidth,
          height: imgWidth,
          id: id,
          type: type,
        });
        devicePointImg.hasBorders = false; //“hasBorders” 和“hasControls”属性来控制对象的边框和顶点的可见性。
        devicePointImg.hasControls = false;
        devicePointImg.hoverCursor = "pointer"; // 鼠标移动到对象上的样式（默认值：move）
        devicePointImg.moveCursor = "pointer"; // 对象拖动时的鼠标样式（默认值：move）
        this.canvasObj.add(devicePointImg);

        this.toResetPointXY(x, y, id);
        this.selectedDeviceObj = {};
        this.selectedDeviceCode = "";

        devicePointImg.on("mousedown", (event) => {
          // 鼠标右键点击平面图中的任一设备，弹出该设备信息
          if (event.button == 3) {
            this.deleteDevicePoint = event.target;

            this.deviceGroupList.forEach((ele) => {
              ele.deviceList.forEach((item) => {
                if (item.deviceCode == event.target.id) {
                  this.infoObj = item;
                  this.infoObj.type = ele.deviceTypeStr;
                }
              });
            });

            this.firstDialogPointX = event.pointer.x - 135;
            this.firstDialogPointY = event.pointer.y - 135;

            this.dialogPointX = this.firstDialogPointX;
            this.dialogPointY = this.firstDialogPointY;

            this.isShowInfoPopover = true;
            // console.log('eventevent=', event)
            // console.log('i=', this.infoObj)
            // console.log('dialogPointX=', this.dialogPointX)
            // console.log('dialogPointY=', this.dialogPointY)
          }
        });

        devicePointImg.on("modified", (event) => {
          this.isShowInfoPopover = false;
          let offX = 0;
          if (event.transform.offsetX < 16) {
            offX = event.e.layerX + (16 - event.transform.offsetX.toFixed(0));
          } else if (event.transform.offsetX > 16) {
            offX = event.e.layerX - (event.transform.offsetX.toFixed(0) - 16);
          }

          let offY = 0;
          if (event.transform.offsetY < 16) {
            offY = event.e.layerY + (16 - event.transform.offsetY.toFixed(0));
          } else if (event.transform.offsetY > 16) {
            offY = event.e.layerY - (event.transform.offsetY.toFixed(0) - 16);
          }
          let vpt = this.canvasObj.viewportTransform;
          var x = (offX - vpt[4]) / vpt[0];
          var y = (offY - vpt[5]) / vpt[3];

          this.toResetPointXY(x, y, id);
        });
      };
    },

    // 赋值点位坐标
    toResetPointXY(x, y, deviceCode) {
      this.deviceGroupList.forEach((ele) => {
        ele.deviceList.forEach((item) => {
          if (item.deviceCode == deviceCode) {
            item.pointX = x;
            item.pointY = y;
          }
        });
      });
    },

    // 弹窗-删除设备的点位
    toDelete() {
      this.$confirm("确定要删除该设备吗？", "提示", {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        type: "warning",
      })
        .then(() => {
          this.canvasObj.remove(this.deleteDevicePoint);

          this.isShowInfoPopover = false;

          this.toResetPointXY(null, null, this.infoObj.deviceCode);
          this.$message({
            type: "success",
            message: "删除成功!",
          });
        })
        .catch(() => {});
    },

    // 保存绑定的点位
    toSave() {
      console.log("this.deviceGroupList=", this.deviceGroupList);
      const list = [];
      this.deviceGroupList.forEach((ele) => {
        ele.deviceList.forEach((item) => {
          list.push(item);
        });
      });
      console.log("list=", list);
      list.forEach((ele) => {
        if (!ele.pointX) {
          ele.pointX = 0;
        }
        if (!ele.pointY) {
          ele.pointY = 0;
        }
      });
      GridManageApi.addList2D(list).then((ret) => {
        this.$message({
          message: "保存成功！",
          type: "success",
        });
      });
    },

    // 重置已绑定的设备点位
    toReset() {
      this.$confirm("确定要重置平面图中的所有点位吗？", "提示", {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        type: "warning",
      })
        .then(() => {
          const list = [];
          this.deviceGroupList.forEach((ele) => {
            ele.deviceList.forEach((item) => {
              list.push(item);
            });
          });
          list.forEach((ele) => {
            ele.pointX = 0;
            ele.pointY = 0;
          });
          GridManageApi.addList2D(list).then((ret) => {
            let obj = this.canvasObj.getObjects();
            obj.forEach((ele) => {
              this.canvasObj.remove(ele);
            });
            this.$message({
              message: "重置成功！",
              type: "success",
            });
          });
        })
        .catch(() => {});
    },

    // 重置图纸
    toResetCanvas() {
      if (this.canvasObj != null) {
        this.canvasObj.setViewportTransform([1, 0, 0, 1, 0, 0]);

        this.dialogPointX = this.infoObj.pointX - 135;
        this.dialogPointY = this.infoObj.pointY - 135;
      }
    },
  },
};
</script>

<style lang="scss" scoped>
.content {
  display: flex;
  margin-top: 10px;
}
.box-left {
  width: 350px;
  height: 100%;
}
.box-right {
  flex: 1;
  height: 100;
  margin-left: 10px;
  padding-top: 0px;
  // overflow: auto;
  overflow: hidden;
  position: relative;
}
.device-info {
  width: 100%;
  height: 100%;
  .device-type {
    color: #686464;
    font-size: 15px;
    font-weight: bold;
    cursor: pointer;
  }
  .device-type-item {
    padding: 8px 15px 0px 15px;
    display: block;
  }
}
.device-info::-webkit-scrollbar-track-piece {
  background: #d3dce6;
}

.device-info::-webkit-scrollbar {
  width: 6px;
  height: 8px;
}

.device-info::-webkit-scrollbar-thumb {
  background: #99a9bf;
  border-radius: 20px;
}

.info-popper {
  width: 260px;
  height: 125px;
  transform-origin: center bottom;
  // z-index: 2150;
  position: absolute;
  top: 163px;
  left: 294px;

  background: #fff;
  min-width: 150px;
  border-radius: 4px;
  border: 1px solid #ebeef5;
  padding: 5px;

  color: #606266;
  line-height: 1.4;
  text-align: justify;
  font-size: 14px;
  box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
  word-break: break-all;
  // margin-bottom: 12px;

  .icon-error {
    position: absolute;
    right: -5px;
    top: -8px;
    font-size: 22px;
    cursor: pointer;
  }
  .info-item {
    margin-bottom: 2px;
  }
  .info-popper-arrow {
    position: absolute;
    display: block;
    width: 0;
    height: 0;
    border-color: transparent;
    border-style: solid;
    border-width: 6px;
    filter: drop-shadow(0 2px 12px rgba(0, 0, 0, 0.03));
    left: 85.5px;
    bottom: -6px;
    left: 50%;
    margin-right: 3px;
    border-top-color: #ebeef5;
    border-bottom-width: 0;
  }
  .info-popper-arrow::after {
    bottom: 1px;
    content: " ";
    border-width: 6px;
    position: absolute;
    display: block;
    width: 0;
    height: 0;
    border-color: transparent;
    border-style: solid;
    margin-left: -6px;
    border-top-color: #fff;
    border-bottom-width: 0;
  }
}

/*form样式-----------------------------------------------------------------------------------------------------*/
/deep/.el-form-item--small.el-form-item {
  margin: 6px 0;
}

/deep/.el-form-item__label {
  text-align: right;
  vertical-align: middle;
  float: left;
  font-size: 14px;
  line-height: 32px;
  padding: 0 4px 0 0;
  -webkit-box-sizing: border-box;
  box-sizing: border-box;
  color: #000000d9;
  font-weight: normal;
}

/deep/ .el-form-item__label::after {
  content: ":";
  position: relative;
  top: -0.5px;
  margin: 0 8px 0 2px;
}

/deep/.el-form-item--small .el-form-item__error {
  padding-top: 2px;
  margin-bottom: -6px;
  position: relative;
}
/deep/.el-page-header__title {
  color: #303133;
}
/deep/.el-page-header__left .el-icon-back {
  color: #303133;
}
</style>
